package com.hunantv.mglive.utils;

import android.content.ContentResolver;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.net.Uri;


import com.hunantv.mglive.common.MaxApplication;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

public class ImageUtils {

    public static interface OnHandleImageListener {
        void onHandled(Bitmap bitmap);
    }


    public static class ImageSize {
        public int mWidth;
        public int mHeight;

        public ImageSize() {
        }


        public ImageSize(int width, int height) {
            setSize(width, height);
        }

        public void setSize(int width, int height) {
            mWidth = width;
            mHeight = height;
        }

        public void setSize(ImageSize size) {
            setSize(size.mWidth, size.mHeight);
        }

        public void setWidth(int width) {
            mWidth = width;
        }

        public void setHeight(int height) {
            mHeight = height;
        }

        public int getWidth() {
            return mWidth;
        }

        public int getHeight() {
            return mHeight;
        }

        @Override
        public boolean equals(Object o) {
            if (!(o instanceof ImageSize)) {
                return false;
            }

            ImageSize rhs = (ImageSize) o;
            return mWidth == rhs.mWidth && mHeight == rhs.mHeight;
        }

        public boolean equals(int width, int height) {
            return mWidth == width && mHeight == height;
        }
    }


    public static BitmapFactory.Options getResourceOptions(
            Resources res, int resId) {

        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(res, resId, options);

        return options;
    }

    public static BitmapFactory.Options getResourceOptions(String filePath) {

        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filePath, options);

        return options;
    }

    public static BitmapFactory.Options getResourceOptions(Uri uri) {
        ContentResolver resolver = MaxApplication.getAppContext().getContentResolver();

        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;

        try {
            InputStream stream = resolver.openInputStream(uri);
            BitmapFactory.decodeStream(stream, new Rect(), options);

            FileUtils.closeStream(stream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        return options;
    }

    public static ImageSize getImageSize(Resources res, int resId) {
        BitmapFactory.Options options = getResourceOptions(res, resId);
        return new ImageSize(options.outWidth, options.outHeight);
    }

    public static ImageSize getImageSize(String filePath) {
        BitmapFactory.Options options = getResourceOptions(filePath);
        return new ImageSize(options.outWidth, options.outHeight);
    }

    public static ImageSize getImageSize(Uri uri) {
        BitmapFactory.Options options = getResourceOptions(uri);
        return new ImageSize(options.outWidth, options.outHeight);
    }

    /**
     * 根据所要求的尺寸获取一个图片采样尺寸.
     */
    public static int calcInSampleSize(
            BitmapFactory.Options options, int requestWidth, int requestHeight) {

        return calcInSampleSize(
                options.outWidth, options.outHeight, requestWidth, requestHeight);
    }

    public static int calcInSampleSize(
            int width, int height, int requestWidth, int requestHeight) {

        int inSampleSize = 1;
        if (requestWidth <= 0 || requestHeight <= 0) {
            return inSampleSize;
        }

        if (width > requestWidth || height > requestHeight) {
            int widthRatio = Math.round((float) width / (float) requestWidth);
            int heightRatio = Math.round((float) height / (float) requestHeight);

            inSampleSize = Math.min(widthRatio, heightRatio);
        }

        return inSampleSize;
    }

    public static Bitmap decodeSampledBitmapFromResource(
            Resources res, int resId) {
        return decodeSampledBitmapFromResource(res, resId, 0, 0);
    }

    /**
     * 根据所要求宽高加载一张图片.
     */
    public static Bitmap decodeSampledBitmapFromResource(
            Resources res, int resId, int requestWidth, int requestHeight) {

        BitmapFactory.Options options = getResourceOptions(res, resId);
        options.inSampleSize = calcInSampleSize(
                options, requestWidth, requestHeight);
        options.inJustDecodeBounds = false;

        try {
            return BitmapFactory.decodeResource(res, resId, options);
        } catch (OutOfMemoryError e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        }

        return null;
    }

    public static Bitmap decodeSampledBitmapFromUri(Uri uri) {
        return decodeSampledBitmapFromUri(uri, 0, 0);
    }

    public static Bitmap decodeSampledBitmapFromUri(
            Uri uri, int requestWidth, int requestHeight) {

        BitmapFactory.Options options = getResourceOptions(uri);
        options.inSampleSize = calcInSampleSize(
                options, requestWidth, requestHeight);
        options.inJustDecodeBounds = false;

        ContentResolver resolver = MaxApplication.getAppContext().getContentResolver();

        try {
            return BitmapFactory.decodeStream(
                    resolver.openInputStream(uri), new Rect(), options);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (OutOfMemoryError e) {
            e.printStackTrace();
        }

        return null;
    }

    public static Bitmap decodeSampledBitmapFromFile(String filePath) {
        return decodeSampledBitmapFromFile(filePath, 0, 0);
    }

    public static Bitmap decodeSampledBitmapFromFile(
            String filePath, int requestWidth, int requestHeight) {

        BitmapFactory.Options options = getResourceOptions(filePath);
        options.inSampleSize = calcInSampleSize(
                options, requestWidth, requestHeight);
        options.inJustDecodeBounds = false;

        try {
            return BitmapFactory.decodeFile(filePath, options);
        } catch (OutOfMemoryError e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        }

        return null;
    }

    public static Bitmap generateMaskBitmap(Bitmap src, Bitmap mask) {
        int width = src.getWidth();
        int height = src.getHeight();

        Bitmap bkg = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bkg);
        Paint paint = new Paint();
        paint.setAntiAlias(true);

        // 绘制 mask.
        Rect dstRc = new Rect(0, 0, width, height);
        Rect maskRc = new Rect(0, 0, mask.getWidth(), mask.getHeight());
        canvas.drawBitmap(mask, maskRc, dstRc, paint);

        // 绘制底图.
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(src, dstRc, dstRc, paint);

        return bkg;
    }

    public static Bitmap generateMaskBitmap(Bitmap src, Drawable maskDrawable) {
        int width = src.getWidth();
        int height = src.getHeight();

        Bitmap bkg = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bkg);
        Paint paint = new Paint();
        paint.setAntiAlias(true);

        // 绘制 mask.
        Rect dstRc = new Rect(0, 0, width, height);
        maskDrawable.setBounds(dstRc);
        maskDrawable.draw(canvas);

        // 绘制底图.
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(src, dstRc, dstRc, paint);

        return bkg;
    }

    public static Bitmap generateMaskBitmap(Resources res, Bitmap src, int maskResId) {
        Bitmap mask = ImageUtils.decodeSampledBitmapFromResource(res, maskResId, 0, 0);
        return generateMaskBitmap(src, mask);
    }

    public static Bitmap generateMaskBitmap(Resources res, Bitmap src, Drawable maskDrawable) {
        return generateMaskBitmap(src, maskDrawable);
    }

    public static Bitmap generateMaskDrawableBitmap(
            Resources res, Bitmap src, int maskResId) {
        return generateMaskBitmap(src, res.getDrawable(maskResId));
    }

    public static Bitmap generateMaskDrawable(
            Resources res,
            Drawable src, Drawable maskDrawable,
            int width, int height) {

        if (width <= 0 || height <= 0) {
            return null;
        }

        Bitmap bkg = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bkg);
        Paint paint = new Paint();
        paint.setAntiAlias(true);

        Rect dstRc = new Rect(0, 0, width, height);
        src.setBounds(dstRc);
        src.draw(canvas);

        return generateMaskBitmap(res, bkg, maskDrawable);
    }

    public static boolean saveBitmapToFile(Bitmap bitmap, String filePath) {
        return saveBitmapToFile(bitmap, filePath, Bitmap.CompressFormat.PNG, 90);
    }

    public static boolean saveBitmapToFile(
            Bitmap bitmap, String filePath,
            Bitmap.CompressFormat format, int quality) {

        File file = new File(filePath);
        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            FileOutputStream out = new FileOutputStream(file);
            bitmap.compress(format, quality, out);

            out.flush();
            out.close();

            return true;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return false;
    }

    public static Bitmap resizeBitmap(Bitmap bitmap, int width, int height) {
        Bitmap outBitmap = Bitmap.createBitmap(width, height, bitmap.getConfig());

        Paint paint = new Paint();
        paint.setAntiAlias(true);

        Canvas canvas = new Canvas(outBitmap);
        canvas.drawBitmap(bitmap, null, new Rect(0, 0, width, height), paint);

        return outBitmap;
    }

    public static ImageSize getMaxScaleSize(Bitmap bitmap, int maxSize) {
        return getMaxScaleSize(bitmap.getWidth(), bitmap.getHeight(), maxSize);
    }

    public static ImageSize getMaxScaleSize(int realWidth, int realHeight, int maxSize) {
        float ratio = realHeight != 0 ? (float) realWidth / (float) realHeight : 1;
        if (ratio == 0) {
            ratio = 1;
        }

        int width = realWidth;
        int height = realHeight;
        if (realWidth > realHeight) {
            if (realWidth > maxSize) {
                width = maxSize;
                height = (int) (width / ratio);
            }
        } else {
            if (realHeight > maxSize) {
                height = maxSize;
                width = (int) (height * ratio);
            }
        }

        return new ImageSize(width, height);
    }
}
